package com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens;

import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.graphics.renderIt.api.renderItGraphicsInterface;
import com.nulldev.util.graphics.renderIt.api.core.RITFont;
import com.nulldev.util.graphics.renderIt.renderer.global.rColor;
import com.nulldev.util.graphics.renderIt.util.renderItUtils;
import com.nulldev.util.graphics.renderIt.util.renderPosition;
import com.nulldev.util.web.flexibleKit.flexRenderer.FlexEnvironment;
import com.nulldev.util.web.flexibleKit.flexRenderer.paths.PathGenerator;
import com.nulldev.util.web.flexibleKit.flexRenderer.styling.fonts.flexFontManager;
import com.nulldev.util.web.flexibleKit.general.RenderOperation;
import com.nulldev.util.web.flexibleKit.global.GlobalRendererSettings;
import com.nulldev.util.web.flexibleKit.jfvParse.Node;

import static com.nulldev.util.web.flexibleKit.flexRenderer.paths.subgens.ParagraphGenerator.isBlankLine;

import java.awt.font.TextAttribute;
import java.util.Collections;

public class HeaderGenerator implements PathGenerator {

	@Override
	public RenderOperation generate(final Node n, final PathGenerationFlags... flags) {
		final RenderOperation ri = new RenderOperation() {

			private RITFont font;

			@Override
			public renderPosition doRender(final renderItGraphicsInterface i, final renderPosition rp, final FlexEnvironment env) {
				final int fontSize = getFontSizeFromNode(
						GlobalRendererSettings.SCALE_TEXT_AUTOMATICALLY ? i.viewport_getWidth() / 32 : flexFontManager.getFontSize("header"), n);
				final String s = n.getTextContent();
				if (isBlankLine(s))
					return rp;
				if (!ArrayUtils.contains(flags, PathGenerationFlags.RENDER_INLINE))
					rp.resetX();
				if (font == null)
					font = i.awt_make_font(deriveForNode(flexFontManager.getFont("sans-serif").getFont(fontSize), fontSize, n));
//				i.submitExtensionData(RequestableExtensions.FR_EXT_PREV_POSITION, rp);
				// FIXME: Use scalable
				final int inc = i.text_scalable(s, rp.getX(), rp.appendGetY(fontSize), font, rColor.BLACK);
//				i.requestViewportHeight(rp.getY());
//				i.runQuirkFix(RenderingQuirks.RESET_X_AFTER_CALL);
				final int tw = renderItUtils.guessTextWidth(fontSize, s);
				if (!ArrayUtils.contains(flags, PathGenerationFlags.RENDER_INLINE)) {
					rp.addY(inc).resetX();
				} else {
					rp.addX(tw);
				}
				return rp.clone().addX(tw);
			}

			@Override
			public Node operationFor() {
				return n;
			}

			@Override
			public boolean keepInline() {
				return ArrayUtils.contains(flags, PathGenerationFlags.RENDER_INLINE);
			}
		};
		return ri;
	}

	private static int getFontSizeFromNode(final int fontSize, final Node n) {
		switch (n.getParentNode().getNodeName()) {
			case "h1":
				return (int) (fontSize * 1.5);
			case "h2":
				return (int) (fontSize * 1.25);
			case "h3":
				return fontSize;
			case "h4":
				return (int) (fontSize * 0.8);
			case "h5":
				return (int) (fontSize * 0.6);
			case "h6":
				return (int) (fontSize * 0.5);
			default:
				throw new UnsupportedOperationException("Unknown node: " + n.getParentNode().getNodeName());
		}
	}

	private static java.awt.Font deriveForNode(final java.awt.Font font, final int fontSize, final Node n) {
		switch (n.getParentNode().getNodeName()) {
			case "h1":
				return font.deriveFont(Collections.singletonMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_ULTRABOLD));
			case "h2":
				return font.deriveFont(Collections.singletonMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_EXTRABOLD));
			case "h3":
				return font.deriveFont(Collections.singletonMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_DEMIBOLD));
			case "h4":
				return font.deriveFont(Collections.singletonMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_SEMIBOLD));
			case "h5":
			case "h6":
				return font.deriveFont(Collections.singletonMap(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD));
			default:
				throw new UnsupportedOperationException("Unknown node: " + n.getParentNode().getNodeName());
		}
	}

}
